home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / groff_src.lha / groff-1.10src / libdriver / printer.cc < prev   
Encoding:
C/C++ Source or Header  |  1995-06-22  |  6.1 KB  |  242 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 2, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  20.  
  21. #include "driver.h"
  22.  
  23. printer *pr = 0;
  24.  
  25. font_pointer_list::font_pointer_list(font *f, font_pointer_list *fp)
  26. : p(f), next(fp)
  27. {
  28. }
  29.  
  30. printer::printer()
  31. : font_table(0), nfonts(0), font_list(0)
  32. {
  33. }
  34.  
  35. printer::~printer()
  36. {
  37.   a_delete font_table;
  38.   while (font_list) {
  39.     font_pointer_list *tem = font_list;
  40.     font_list = font_list->next;
  41.     delete tem->p;
  42.     delete tem;
  43.   }
  44.   if (ferror(stdout) || fflush(stdout) < 0)
  45.     fatal("output error");
  46. }
  47.  
  48. void printer::load_font(int n, const char *nm)
  49. {
  50.   assert(n >= 0);
  51.   if (n >= nfonts) {
  52.     if (nfonts == 0) {
  53.       nfonts = 10;
  54.       if (nfonts <= n)
  55.     nfonts = n + 1;
  56.       font_table = new font *[nfonts];
  57.       for (int i = 0; i < nfonts; i++)
  58.     font_table[i] = 0;
  59.     }
  60.     else {
  61.       font **old_font_table = font_table;
  62.       int old_nfonts = nfonts;
  63.       nfonts *= 2;
  64.       if (n >= nfonts)
  65.     nfonts = n + 1;
  66.       font_table = new font *[nfonts];
  67.       int i;
  68.       for (i = 0; i < old_nfonts; i++)
  69.     font_table[i] = old_font_table[i];
  70.       for (i = old_nfonts; i < nfonts; i++)
  71.     font_table[i] = 0;
  72.       a_delete old_font_table;
  73.     }
  74.   }
  75.   font *f = find_font(nm);
  76.   font_table[n] = f;
  77. }
  78.  
  79. font *printer::find_font(const char *nm)
  80. {
  81.   for (font_pointer_list *p = font_list; p; p = p->next)
  82.     if (strcmp(p->p->get_name(), nm) == 0)
  83.       return p->p;
  84.   font *f = make_font(nm);
  85.   if (!f)
  86.     fatal("sorry, I can't continue");
  87.   font_list = new font_pointer_list(f, font_list);
  88.   return f;
  89. }
  90.  
  91. font *printer::make_font(const char *nm)
  92. {
  93.   return font::load_font(nm);
  94. }
  95.  
  96. void printer::end_of_line()
  97. {
  98. }
  99.  
  100. void printer::special(char *, const environment *)
  101. {
  102. }
  103.  
  104. void printer::draw(int, int *, int, const environment *)
  105. {
  106. }
  107.  
  108. void printer::set_ascii_char(unsigned char c, const environment *env, 
  109.                  int *widthp)
  110. {
  111.   char buf[2];
  112.   buf[0] = c;
  113.   buf[1] = '\0';
  114.   set_special_char(buf, env, widthp);
  115. }
  116.  
  117. void printer::set_special_char(const char *nm, const environment *env,
  118.                   int *widthp)
  119. {
  120.   int i = font::name_to_index(nm);
  121.   int fn = env->fontno;
  122.   if (fn < 0 || fn >= nfonts) {
  123.     error("bad font position `%1'", fn);
  124.     return;
  125.   }
  126.   font *f = font_table[fn];
  127.   if (f == 0) {
  128.     error("no font mounted at `%1'", fn);
  129.     return;
  130.   }
  131.   if (!f->contains(i)) {
  132.     if (nm[0] != '\0' && nm[1] == '\0')
  133.       error("font `%1' does not contain ascii character `%2'",
  134.         f->get_name(),
  135.         nm[0]);
  136.     else
  137.       error("font `%1' does not contain special character `%2'",
  138.         f->get_name(),
  139.         nm);
  140.     return;
  141.   }
  142.   int w = f->get_width(i, env->size);
  143.   if (widthp)
  144.     *widthp = w;
  145.   set_char(i, f, env, w);
  146. }
  147.  
  148. void printer::set_numbered_char(int num, const environment *env, int *widthp)
  149. {
  150.   int i = font::number_to_index(num);
  151.   int fn = env->fontno;
  152.   if (fn < 0 || fn >= nfonts) {
  153.     error("bad font position `%1'", fn);
  154.     return;
  155.   }
  156.   font *f = font_table[fn];
  157.   if (f == 0) {
  158.     error("no font mounted at `%1'", fn);
  159.     return;
  160.   }
  161.   if (!f->contains(i)) {
  162.     error("font `%1' does not contain numbered character %2",
  163.       f->get_name(),
  164.       num);
  165.     return;
  166.   }
  167.   int w = f->get_width(i, env->size);
  168.   if (widthp)
  169.     *widthp = w;
  170.   set_char(i, f, env, w);
  171. }
  172.  
  173. // This utility function adjusts the specified center of the
  174. // arc so that it is equidistant between the specified start
  175. // and end points. (p[0], p[1]) is a vector from the current
  176. // point to the center; (p[2], p[3]) is a vector from the 
  177. // center to the end point.  If the center can be adjusted,
  178. // a vector from the current point to the adjusted center is
  179. // stored in c[0], c[1] and 1 is returned.  Otherwise 0 is
  180. // returned.
  181.  
  182. #if 1
  183. int printer::adjust_arc_center(const int *p, double *c)
  184. {
  185.   // We move the center along a line parallel to the line between
  186.   // the specified start point and end point so that the center
  187.   // is equidistant between the start and end point.
  188.   // It can be proved (using Lagrange multipliers) that this will
  189.   // give the point nearest to the specified center that is equidistant
  190.   // between the start and end point.
  191.  
  192.   double x = p[0] + p[2];    // (x, y) is the end point
  193.   double y = p[1] + p[3];
  194.   double n = x*x + y*y;
  195.   if (n != 0) {
  196.     c[0]= double(p[0]);
  197.     c[1] = double(p[1]);
  198.     double k = .5 - (c[0]*x + c[1]*y)/n;
  199.     c[0] += k*x;
  200.     c[1] += k*y;
  201.     return 1;
  202.   }
  203.   else
  204.     return 0;
  205. }
  206. #else
  207. int printer::adjust_arc_center(const int *p, double *c)
  208. {
  209.   int x = p[0] + p[2];    // (x, y) is the end point
  210.   int y = p[1] + p[3];
  211.   // Start at the current point; go in the direction of the specified
  212.   // center point until we reach a point that is equidistant between
  213.   // the specified starting point and the specified end point. Place
  214.   // the center of the arc there.
  215.   double n = p[0]*double(x) + p[1]*double(y);
  216.   if (n > 0) {
  217.     double k = (double(x)*x + double(y)*y)/(2.0*n);
  218.     // (cx, cy) is our chosen center
  219.     c[0] = k*p[0];
  220.     c[1] = k*p[1];
  221.     return 1;
  222.   }
  223.   else {
  224.     // We would never reach such a point.  So instead start at the
  225.     // specified end point of the arc.  Go towards the specified
  226.     // center point until we reach a point that is equidistant between
  227.     // the specified start point and specified end point. Place
  228.     // the center of the arc there.
  229.     n = p[2]*double(x) + p[3]*double(y);
  230.     if (n > 0) {
  231.       double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
  232.       // (c[0], c[1]) is our chosen center
  233.       c[0] = p[0] + k*p[2];
  234.       c[1] = p[1] + k*p[3];
  235.       return 1;
  236.     }
  237.     else
  238.       return 0;
  239.   }
  240. }  
  241. #endif
  242.